package com.itheima.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.common.core.domain.AjaxResult;
import com.itheima.common.utils.DateUtils;
import com.itheima.common.utils.bean.BeanUtils;
import com.itheima.common.utils.file.FileTypeUtils;
import com.itheima.server.Enum.ClueStatus;
import com.itheima.server.domain.*;
import com.itheima.server.dto.ActiReportQueryDto;
import com.itheima.server.mapper.ContractMapper;
import com.itheima.server.dto.ContractStatisticsDto;
import com.itheima.server.dto.PageDto;
import com.itheima.server.mapper.BusinessMapper;
import com.itheima.server.mapper.ContractMapper;
import com.itheima.server.service.*;
import com.itheima.server.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.pagehelper.PageHelper;
import com.itheima.server.dto.ReportClueDto;
import com.itheima.server.mapper.ClueMapper;
import com.itheima.server.service.ReportService;
import com.itheima.server.vo.ReportClueVo;
import lombok.RequiredArgsConstructor;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
@Slf4j
public class ReportServiceImpl implements ReportService {


    private static final String DATE_PATTERN = "yyyy-MM-dd";

    private final ActiviteService activiteService;
    private final ClueService clueService;
    private final BusinessDetailService businessDetailService;
    private final ContractService contractService;
    private final ClueMapper clueMapper;
    private final ContractMapper contractMapper;
    private final BusinessMapper businessMapper;



    /**
     * 获取渠道统计的活动列表
     * @param dto
     * @return
     */
    @Override
    public List<ActiReportQueryVO> activityStatisticsList(ActiReportQueryDto dto) {
        Page<Activite> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<Activite> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(dto.getName()),Activite::getName,dto.getName());
        wrapper.like(StringUtils.hasText(dto.getCode()),Activite::getCode,dto.getCode());
        if (StringUtils.hasText(dto.getBeginCreateTime())&&StringUtils.hasText(dto.getEndCreateTime())){
            try {
                Date createTime = DateUtils.parseDate(dto.getBeginCreateTime(), DATE_PATTERN);
                Date endTime = DateUtils.parseDate(dto.getEndCreateTime(), DATE_PATTERN);
                wrapper.between(Activite::getCreateTime,createTime,endTime);
            }catch (Exception e){
                log.error("日期解析出错 {}",e);
            }
        }
        activiteService.page(page,wrapper);
        List<ActiReportQueryVO> collect = page.getRecords().stream().map(item -> {
            return getActiQueryVo(item);
        }).collect(Collectors.toList());

        return collect;
    }



    /**
     * 获取每个活动的线索数，伪线索数，商机数，客户数……
     * @param activite
     * @return
     */
    private ActiReportQueryVO getActiQueryVo(Activite activite){
        ActiReportQueryVO queryVO = new ActiReportQueryVO();
        BeanUtils.copyProperties(activite,queryVO);

        //获取线索总数
        LambdaQueryWrapper<Clue> clueWrapper = new LambdaQueryWrapper<>();
        clueWrapper.eq(Clue::getActivityId,activite.getId());
        Integer count = clueService.count(clueWrapper);
        queryVO.setCluesNum(count==null?0:count);

        //获取伪线索数
        clueWrapper.eq(Clue::getStatus, ClueStatus.INVALID.status);
        count = clueService.count(clueWrapper);
        queryVO.setFalseCluesNum(count==null?0:count);

        //获取转化为商机数量
        LambdaQueryWrapper<BusinessDetail> busWrapper = new LambdaQueryWrapper<>();
        busWrapper.eq(BusinessDetail::getActivityId,activite.getId());
        count = businessDetailService.count(busWrapper);
        queryVO.setBusinessNum(count==null?0:count);

        //转化为客户数
        LambdaQueryWrapper<Contract> contractWrapper = new LambdaQueryWrapper<>();
        contractWrapper.eq(Contract::getActivityId,activite.getId());
        count = contractService.count(contractWrapper);
        queryVO.setCustomersNum(count==null?0:count);

        //获取成本和收入
        Integer amount = contractService.getActiAmountById(activite.getId());
        Integer cost = 0;
        if (amount!=null&&activite.getDiscount()!=null){
            cost += (int) (amount/activite.getDiscount());
        }
        if (count!=null && activite.getVouchers()!=null){
            cost+=count*activite.getVouchers();
        }
        queryVO.setAmount(amount == null?0:amount);
        queryVO.setCost(cost);
        return queryVO;
    }



    @Override
    public List<ReportClueVo> reportClueList(ReportClueDto dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        com.github.pagehelper.Page<ReportClueVo> page = clueMapper.reportClueList(dto);

        return page.getResult();
    }

    /**
     * 获取渠道统计 图表1
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(String beginTime, String endTime) {

        List<Map<String, Object>> countList = clueMapper.chanelStatistics(beginTime,endTime);
        List<Map<String, Object>> collect = countList.stream().filter(item -> item.containsKey("channel") && item.containsKey("num"))
                .collect(Collectors.toList());
        return collect;
    }

    /**
     * 获取渠道统计 图表2
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public List<Map<String, Object>> activityStatistics(String beginTime, String endTime) {

        List<Map<String, Object>> countList = contractMapper.activityStatistics(beginTime,endTime);
        List<Map<String, Object>> collect = countList.stream().filter(item -> item.containsKey("activity") && item.containsKey("num")).collect(Collectors.toList());
        return collect;
    }



    @Override
    public List<DeptContractReportVo> getdeptStatisticsList(PageDto dto, String start1, String end2) {

        LocalDate begin = null;
        LocalDate end = null;
        if(start1!=""&& end2!=""){
            begin = LocalDate.parse(start1);
            end = LocalDate.parse(end2);
        }
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        com.github.pagehelper.Page<DeptContractReportVo> page = contractMapper.getdeptStatisticsList( begin,end);

        return page.getResult();
    }

    @Override
    public ReportClueChartVo getClueChart(Date begin, Date end) {
        //y
        ArrayList<ReportClueChartPartVo> series = new ArrayList<>();
        //x
        ArrayList<Date> xAxis = new ArrayList<>();

        //线索总数量
        ReportClueChartPartVo countPart = new ReportClueChartPartVo();
        countPart.setName("线索总数量");
        ArrayList<Integer> countData = new ArrayList<>();
        countPart.setData(countData);

        //线索新增数量
        ReportClueChartPartVo newPart = new ReportClueChartPartVo();
        newPart.setName("线索新增数量");
        ArrayList<Integer> newData = new ArrayList<>();
        newPart.setData(newData);

        while (begin.getTime()<=end.getTime()){
            xAxis.add(begin);
            //获取当天开始的时间
            // Date 转 LocalDate
            LocalDateTime beginTime = LocalDateTime.of(begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MAX);

            //查询这天的总数量
            LambdaQueryWrapper<Clue> countWrapper = new LambdaQueryWrapper<>();
            countWrapper.le(Clue::getCreateTime,endTime);
            int count = clueService.count(countWrapper);
            countData.add(count);

            //这天新增数量
            LambdaQueryWrapper<Clue> newWrapper = new LambdaQueryWrapper<>();
            newWrapper.between(Clue::getCreateTime,beginTime,endTime);
            int newCount = clueService.count(newWrapper);
            newData.add(newCount);

            //天数加1
            begin = DateUtils.addDays(begin,1);

        }
        //添加series
        series.add(newPart);
        series.add(countPart);

        //数据封装
        ReportClueChartVo chartVo = new ReportClueChartVo();
        chartVo.setSeries(series);
        chartVo.setXAxis(xAxis);

        return chartVo;
    }

    @Override
    public VulnerabilityMapVo getVulnerabilityMap(Date begin, Date end) {

        LocalDateTime beginTime = LocalDateTime.of(begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MAX);

        //获取线索总数
        LambdaQueryWrapper<Clue> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(Clue::getCreateTime,beginTime,endTime);
        Integer cluesNums = clueService.count(wrapper);

        //获取有效线索数
        LambdaQueryWrapper<Clue> clueWrapper = new LambdaQueryWrapper<>();
        clueWrapper.eq(Clue::getStatus, ClueStatus.PENDING.status)
                .or().eq(Clue::getStatus, ClueStatus.ASSIGNED.status)
                .between(Clue::getCreateTime,beginTime,endTime);
       Integer effectiveCluesNums = clueService.count(clueWrapper);

        //获取转化为商机数量
        LambdaQueryWrapper<Clue> clueBusinessWrapper = new LambdaQueryWrapper<>();
        clueBusinessWrapper.eq(Clue::getStatus, ClueStatus.BUSINESS.status).
                between(Clue::getCreateTime,beginTime,endTime);
        Integer businessNums = clueService.count(clueBusinessWrapper);

        //转化为客户数
        LambdaQueryWrapper<Clue> clueContractWrapper = new LambdaQueryWrapper<>();
        clueContractWrapper.eq(Clue::getStatus, ClueStatus.CONTRACT.status).
                between(Clue::getCreateTime,beginTime,endTime);
        Integer contractNums = clueService.count(clueContractWrapper);


        VulnerabilityMapVo vo = new VulnerabilityMapVo();
        vo.setCluesNums(cluesNums);
        vo.setEffectiveCluesNums(effectiveCluesNums);
        vo.setBusinessNums(businessNums);
        vo.setContractNums(contractNums);


        return vo;
    }

    /**
     * 获取合同统计列表
     * @param dto
     * @return
     */
    public AjaxResult getContractStatisticsList(ContractStatisticsDto dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());

        // 使用正确的解析方式，将日期字符串解析为 LocalDate，再转换为 LocalDateTime
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime beginCreateTime = LocalDate.parse(dto.getBeginCreateTime(), formatter).atStartOfDay();
        LocalDateTime endCreateTime = LocalDate.parse(dto.getEndCreateTime(), formatter).atTime(23, 59, 59);

        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(!ObjectUtils.isEmpty(dto.getChannel()), Contract::getChannel, dto.getChannel())
                .eq(!ObjectUtils.isEmpty(dto.getDeptId()), Contract::getDeptId, dto.getDeptId())
                .eq(!ObjectUtils.isEmpty(dto.getCreateBy()), Contract::getCreateBy, dto.getCreateBy())
                .between(Contract::getCreateTime, beginCreateTime, endCreateTime);

        com.github.pagehelper.Page<Contract> result =  (com.github.pagehelper.Page<Contract>) contractMapper.selectList(wrapper);

        long total = result.getTotal();
        List<Contract> rows = result.getResult();

        AjaxResult ajax = new AjaxResult(200, "查询成功");
        ajax.put("total",total);
        ajax.put("rows",rows);
        ajax.put("params",null);
        return ajax;
    }

    /**
     * 获取线索新增和总数量的对比数据
     * @param begin
     * @param end
     * @return
     */
    public CustVo getPairdDataNewAndOldClue(Date begin, Date end) {
        //获取begin 到 end 的日期
        List<Date> dateList = new ArrayList<>();

        while (begin.getTime()<=end.getTime()){
            dateList.add(begin);
            begin = DateUtils.addDays(begin,1);
        }

        //将dateList 转换成 LocalDate
        List<LocalDate> localDateList = dateList.stream().map(date -> date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()).collect(Collectors.toList());


        List<Contract> contractList = contractMapper.selectList(null);
        ArrayList<Integer> newIncreatement = new ArrayList<>();
        ArrayList<Integer> totalCount = new ArrayList<>();

        //先初始化数组
        for (int i = 0; i < dateList.size(); i++) {
            newIncreatement.add(0);
            totalCount.add(0);
        }

        int index = 0;
        for (Date date : dateList) {
            for (Contract contract : contractList) {
                Date createTime = contract.getCreateTime();
                //只要date 的日期部分和createTime的日期部分相同
                if (date != null && createTime != null && DateUtils.isSameDay(date, createTime)){
                    newIncreatement.set(index, newIncreatement.get(index) + 1);
                }

                //获取createTime的日期部分
                if (createTime != null) {
                    LocalDate createDay = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    LocalDate dateDay = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    if (createDay.equals(dateDay)){
                        totalCount.set(index, totalCount.get(index) + 1);
                    }
                }
            }
            //每一天遍历完没有数据设置默认数据
            index++;
            if (index == dateList.size()){
                break;
            }
            //第二天的初始化总数因该是第前一天的总数之和
            if (index > 0){
                totalCount.set(index, totalCount.get(index - 1));
            }
        }

        ReportClueChartPartVo vo1 = new ReportClueChartPartVo();
        vo1.setName("新增客户数");
        vo1.setData(newIncreatement);

        ReportClueChartPartVo vo2 = new ReportClueChartPartVo();
        vo2.setName("总客户数");
        vo2.setData(totalCount);

        CustVo custVo = new CustVo();
        custVo.setXAxis(localDateList);
        ArrayList<ReportClueChartPartVo> vo = new ArrayList<>();
        vo.add(vo1);
        vo.add(vo2);
        custVo.setSeries(vo);

        return custVo;
    }

    /**
     * 获取学科分布统计
     * @param
     * @return
     */
    public List<SubjectStatisticsVo> getSubjectStatistics(Date begin, Date end) {
        //获取begin 到 end 的日期
        List<Date> dateList = new ArrayList<>();

        while (begin.getTime()<=end.getTime()){
            dateList.add(begin);
            begin = DateUtils.addDays(begin,1);
        }

        HashMap<Integer, String> map = new HashMap<>();
        map.put(1,"Java");
        map.put(2,"前端");
        map.put(3,"人工智能");
        map.put(4,"大数据");
        map.put(5,"Python");
        map.put(6,"测试");
        map.put(7,"新媒体");
        map.put(8,"产品经理");
        map.put(9,"UI设计");

        List<Contract> contractList = contractMapper.selectList(null);

        ArrayList<SubjectStatisticsVo> voList = new ArrayList<>();

        Boolean flag = false;

        for (Date date : dateList) {
            for (Contract contract : contractList) {
                Date createTime = contract.getCreateTime();
                //只要date 的日期部分和createTime的日期部分相同 就是目标数据
                if (date!=null&&createTime!=null&&DateUtils.isSameDay(date,createTime)){
                    //获取数据的学科
                    String sub = map.get(contract.getSubject());
                    //去voList中去找
                    if (ObjectUtils.isEmpty(voList)){
                        SubjectStatisticsVo vo = new SubjectStatisticsVo();
                        vo.setSubject(sub);
                        vo.setNum(1);
                        voList.add(vo);
                    } else {
                        for (SubjectStatisticsVo vo : voList) {
                            if (vo.getSubject().equals(sub)){
                                vo.setNum(vo.getNum() + 1);
                                flag = true;
                            }
                        }
                        if (flag == false){
                            SubjectStatisticsVo voTemp = new SubjectStatisticsVo();
                            voTemp.setSubject(sub);
                            voTemp.setNum(1);
                            voList.add(voTemp);
                        }
                    }
                }
                flag = false;
            }
        }

        return voList;
    }



/**
     * 获取销售统计列表
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesStatisticsVo getSalesStatistics(String begin, String end) {
      LocalDate  beginTime = LocalDate.parse(begin);
      LocalDate  endTime = LocalDate.parse(end);
      //从合同表中查询
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(Contract::getCreateTime,beginTime,endTime);
       List<Map<String,Object>> contracts = contractMapper.getSalesStatistics(beginTime,endTime);
        ArrayList<String> arrayList = new ArrayList<>();
        ArrayList<BigDecimal> integers = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        contracts.forEach(c->{
            LocalDateTime t =(LocalDateTime) c.get("time");
            arrayList.add(t.format(formatter));
            BigDecimal order = (BigDecimal)c.get("orders");
            integers.add(order);
        });
        SalesStatisticsVo salesStatisticsVo = new SalesStatisticsVo();
        ArrayList<SaleStatisticsDataVo> saleStatisticsDataVos = new ArrayList<>();
            String name = "销售统计";
        SaleStatisticsDataVo dataVo = new SaleStatisticsDataVo(name, integers);
        saleStatisticsDataVos.add(dataVo);
        salesStatisticsVo.setSeries(saleStatisticsDataVos);
        salesStatisticsVo.setXAxis(arrayList);

        return salesStatisticsVo;
    }

    /**
     * 获取渠道合同数金额统计列表
     * @param dto
     * @param start1
     * @param end2
     * @return
     */
    @Override
    public List<ChannelContractReportVo> getChannelStatisticsList(PageDto dto, String start1, String end2) {
        LocalDate begin = null;
        LocalDate end = null;
        if(start1!=""&& end2!=""){
            begin = LocalDate.parse(start1);
            end = LocalDate.parse(end2);
        }
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        com.github.pagehelper.Page<ChannelContractReportVo> page = contractMapper.getChannerStatisticsList( begin,end);

        return page.getResult();

    }

    /**
     * 获取归属人合同数金额统计列表
     * @param dto
     * @param start1
     * @param end2
     * @return
     */

    @Override
    public List<OwnerShipContractReprtVo> getOwnerStatisticsList(PageDto dto, String start1, String end2) {
        LocalDate begin = null;
        LocalDate end = null;
        if(start1!=""&& end2!=""){
            begin = LocalDate.parse(start1);
            end = LocalDate.parse(end2);
        }
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        com.github.pagehelper.Page<OwnerShipContractReprtVo> page = contractMapper.getOwnerStatisticsList( begin,end);
        return page.getResult();
    }
}
